﻿using IOA.MES.Client.Common;
using Newtonsoft.Json;
using NLog;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using System.Windows.Media.Imaging;

namespace IOA.MES.Client.Framing
{
    /// <summary>
    /// WinFramingImage.xaml 的交互逻辑
    /// </summary>
    public partial class WinFramingImage : Window
    {
        private JHCap.SnapThreadCallback callback = new JHCap.SnapThreadCallback(CallbackFunction);
        private List<int> cameraIndexes = new List<int>();
        private int cameraCount = 0, width = 0, height = 0;
        public WinFramingImage()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            this.Width = SystemParameters.WorkArea.Width / 3.0;
            this.Height = SystemParameters.WorkArea.Height;
            this.Left = SystemParameters.WorkArea.Width / 3.0 * 2;
            this.Top = 0;
            var hwnd_source = (System.Windows.Interop.HwndSource)PresentationSource.FromVisual(this);
            var hwnd_target = hwnd_source.CompositionTarget;
            hwnd_target.RenderMode = System.Windows.Interop.RenderMode.SoftwareOnly;
            InitWindow();
        }

        private void btnReload_Click(object sender, RoutedEventArgs e)
        {
            var btnName = (sender as System.Windows.Controls.Button)?.Name;
            switch (btnName)
            {
                case "btnReload":
                    InitWindow();
                    break;
                case "btnRandom":
                    InitWindow(true);
                    break;
            }
        }

        private void InitWindow(bool random = false)
        {
            JHCap.CameraGetCount(ref cameraCount);
            gridImagesContainer.RowDefinitions.Clear();
            var cameraIndexesStr = BaseEnv.GetStorage("CameraIndexes");
            cameraIndexes = string.IsNullOrWhiteSpace(cameraIndexesStr) ? new List<int>() : JsonConvert.DeserializeObject<List<int>>(cameraIndexesStr);
            if (!cameraIndexes.Any())
            {
                for (var i = 0; i < cameraCount; i++)
                {
                    cameraIndexes.Add(i);
                }
                BaseEnv.SetStorage("CameraIndexes", JsonConvert.SerializeObject(cameraIndexes));
            }
            cameraIndexes = cameraIndexes.Where(_ => _ < cameraCount).ToList();

            if (random)
            {
                var newCameraIndexes = new List<int>();
                for (var i = 0; i < cameraCount; i++)
                {
                    while (true)
                    {
                        var curIndex = new Random().Next(0, cameraCount);
                        if (!newCameraIndexes.Contains(curIndex))
                        {
                            newCameraIndexes.Add(curIndex);
                            break;
                        }
                    }
                }
                cameraIndexes = newCameraIndexes;
                BaseEnv.SetStorage("CameraIndexes", JsonConvert.SerializeObject(cameraIndexes));
            }

            for (int i = 0; i < cameraIndexes.Count; i++)
            {
                StringBuilder name = new StringBuilder();
                StringBuilder model = new StringBuilder();
                width = (int)gridImagesContainer.ActualWidth;
                height = (int)(gridImagesContainer.ActualHeight / cameraCount);

                gridImagesContainer.RowDefinitions.Add(new RowDefinition());
                JHCap.CameraGetName(cameraIndexes[i], name, model);
                JHCap.CameraInit(cameraIndexes[i]);
                JHCap.CameraSetHighspeed(cameraIndexes[i], false);

                var host = new WindowsFormsHost();
                host.Width = width;
                host.Height = height;
                host.Child = new System.Windows.Forms.Control();
                var pictureBox = new PictureBox();
                pictureBox.Width = width;
                pictureBox.Height = height;
                host.Child.Controls.Add(pictureBox);
                host.Margin = new Thickness(10, 10, 10, 10);
                host.SetValue(Grid.RowProperty, i);
                host.SetValue(Grid.ColumnProperty, 0);
                gridImagesContainer.Children.Add(host);

                JHCap.CameraSetDelay(0, 0);
                JHCap.CameraSetResolution(0, 0, ref width, ref height);
                JHCap.CameraPlay(cameraIndexes[i], pictureBox.Handle, callback);
            }
        }

        private static int CallbackFunction(IntPtr pImageBuffer, int width, int height, int format)  //回调函数定义
        {
            return 0;
        }

        public string GetImage(int cameraIndex)
        {
            var directory = $"{Environment.CurrentDirectory}\\CameraImages\\";
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
            var fileName = $"{directory}{Guid.NewGuid().ToString()}.jpg";
            for (var i = 0; i < 20; i++)
            {
                var result = JHCap.CameraSaveJpegB(cameraIndex, fileName, true);
                if (result == JHCap.API_OK && File.Exists(fileName))
                {
                    for (var j = 0; j < 10; j++)
                    {
                        if (!File.Exists(fileName))
                        {
                            CommonMessage.Log(LogLevel.Warn, $"第{j + 1}次检测到摄像机返回拍照成功，实际文件不存在：{fileName}");
                            Thread.Sleep(500);
                        }
                        else
                        {
                            break;
                        }
                    }
                    return fileName;
                }
                CommonMessage.Log(LogLevel.Warn, $"当前组件第{i + 1}次拍照失败：{fileName}");
                Thread.Sleep(500);
            }
            return string.Empty;
        }

        public byte[] GetUnionImage(string barCode, string machineName)
        {
            var files = new List<string>();
            foreach (var index in cameraIndexes)
            {
                files.Add(GetImage(index));
            }

            var bitmap = UnionImages(barCode, machineName, files);
            foreach (var file in files)
            {
                try
                {
                    File.Delete(file);
                }
                catch (Exception ex)
                {
                    CommonMessage.Log(LogLevel.Fatal, $"单个图片删除失败：{file}", ex);
                }
            }

            var bytes = new byte[] { };
            for (int i = 0; i < 100; i++)
            {
                var fileName = $"{BaseEnv.LocalDirectory}\\UnionImages\\{DateTime.Today.ToString("yyyyMMdd")}\\{barCode}" + (i <= 0 ? "" : $"_{i}") + ".jpg";
                if (!Directory.Exists(Path.GetDirectoryName(fileName)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                }
                if (!File.Exists(fileName))
                {
                    bitmap.Save(fileName, ImageFormat.Jpeg);
                    bitmap.Dispose();
                    bytes = File.ReadAllBytes(fileName);
                    break;
                }
            }

            new TaskFactory().StartNew(() =>
            {
                var directories = Directory.GetDirectories($"{BaseEnv.LocalDirectory}\\UnionImages");
                foreach (var item in directories)
                {
                    try
                    {
                        if (string.Compare(item, $"{BaseEnv.LocalDirectory}\\UnionImages\\{DateTime.Today.AddDays(-2):yyyyMMdd}") < 0)
                        {
                            Directory.Delete(item, true);
                        }
                    }
                    catch (Exception ex)
                    {
                        CommonMessage.Log(LogLevel.Fatal, $"删除目录失败，目录：{item}，错误信息：{ex.Message}", ex);
                    }
                }
            });
            return bytes;
        }
        /// <summary>
        /// 保存图片
        /// </summary>
        /// <param name="framingIndex"></param>
        /// <param name="barCode"></param>
        /// <param name="machineName"></param>
        /// <returns></returns>
        public byte[] GetUnionImages(string barCode, string machineName,out string imageName)
        {
            var bytes = new byte[] { };
            var files = new List<string>();
            imageName = string.Empty;
            foreach (var index in cameraIndexes)
            {
                files.Add(GetImage(index));
            }
            //图片合并
            var bitmap = UnionImagesPrint(barCode, machineName, files);
            if(bitmap == null)
            {
                CommonMessage.Alert(this, "相机拍照失败，请重新扫码拍照");
                return bytes;
            }

            for (int i = 0; i < 100; i++)
            {
                var fileName = $"{FramingIndex.PhotoFile}\\UnionImages\\{DateTime.Today.ToString("yyyy-MM-dd")}\\OK\\{barCode}" + (i <= 0 ? "" : $"_{i}") + ".jpg";
                if (!Directory.Exists(Path.GetDirectoryName(fileName)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                }
                if (!File.Exists(fileName))
                {
                    ImageFormat format = ImageFormat.Jpeg;
                    CommonMessage.Log(LogLevel.Info, $"条码：{barCode}，图片位置：{fileName}，准备创建中。。。");
                    bitmap.Save(fileName, format);
                    imageName = fileName;
                    CommonMessage.Log(LogLevel.Info, $"条码：{barCode}，图片位置：{fileName}，创建成功。。。。");
                    bitmap.Dispose();
                    bytes = File.ReadAllBytes(fileName);
                    break;
                }
                else
                {
                    CommonMessage.Log(LogLevel.Error, $"条码：{barCode}，文件位置：{fileName}，已经存在。。。");
                }
            }
            return bytes;
        }
        /// <summary>
        /// 保存图片
        /// </summary>
        /// <param name="framingIndex"></param>
        /// <param name="barCode"></param>
        /// <param name="machineName"></param>
        /// <returns></returns>
        //public byte[] GetUnionImage(FramingIndex framingIndex,string barCode, string machineName)
        //{
        //    var files = new List<string>();
        //    foreach (var index in cameraIndexes)
        //    {
        //        files.Add(GetImage(index));
        //    }
        //    //图片合并
        //    var bitmap = UnionImages(framingIndex,barCode, machineName, files);
        //    var bytes = new byte[] { };
        //    for (int i = 0; i < 100; i++)
        //    {
        //        var fileName = $"{framingIndex.PhotoFile}\\UnionImages\\{DateTime.Today.ToString("yyyyMMdd")}\\OK\\{barCode}" + (i <= 0 ? "" : $"_{i}") + ".jpg";
        //        if (!Directory.Exists(Path.GetDirectoryName(fileName)))
        //        {
        //            Directory.CreateDirectory(Path.GetDirectoryName(fileName));
                    
        //        }
        //        if (!File.Exists(fileName))
        //        {
        //            bitmap.Save(fileName, ImageFormat.Jpeg);
        //            FramingIndex._records.Clear();
        //            FramingIndex._records.Add(new Models.Response.ViaSiteRecord
        //            {
        //                Code = barCode,MachineName = machineName,OperateTime = DateTime.Now.ToString("F")
        //            });
        //            bitmap.Dispose();
        //            FramingIndex.FileName = fileName;
        //            //bytes = File.ReadAllBytes(fileName);
        //            break;
        //        }
        //    }
        //    //CommonMessage.Log(LogLevel.Info, $"图片拼接完成");
        //    //new TaskFactory().StartNew(() =>
        //    //{
        //    //    var directories = Directory.GetDirectories($"{framingIndex.PhotoFile}\\UnionImages");
        //    //    foreach (var item in directories)
        //    //    {
        //    //        try
        //    //        {
        //    //            if (string.Compare(item, $"{framingIndex.PhotoFile}\\UnionImages\\{DateTime.Today.AddDays(-2):yyyyMMdd}") < 0)
        //    //            {
        //    //                Directory.Delete(item, true);
        //    //            }
        //    //        }
        //    //        catch (Exception ex)
        //    //        {
        //    //            CommonMessage.Log(LogLevel.Fatal, $"删除目录失败，目录：{item}，错误信息：{ex.Message}", ex);
        //    //        }
        //    //    }
        //    //});
        //    return bytes;
        //}

        private Bitmap UnionImages(string barCode, string machineName, List<string> images)
        {
            var imageModels = new List<System.Drawing.Image>();
            foreach (var path in images)
            {
                var image = System.Drawing.Image.FromFile(path);
                imageModels.Add(image);
            }
            var finaImage = new Bitmap(imageModels.Sum(_ => _.Width) + 20, imageModels.Max(_ => _.Height));
            var g = Graphics.FromImage(finaImage);
            g.Clear(Color.White);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;//设置图片质量

            var x = 0;
            var position = new List<string> { "L", "Z", "R" };
            foreach (var image in imageModels)
            {
                g.DrawImage(image, x, 0, image.Width, image.Height);
                var font = new Font("宋体 ", 40);
                var brush = new SolidBrush(Color.Red);
                var str = $"NO:{barCode},Line:{machineName} {position[imageModels.IndexOf(image)]},Time:{DateTime.Now:yyyy/MM/dd HH:mm:ss}";
                var size1 = g.MeasureString(str, font, PointF.Empty, StringFormat.GenericDefault);
                g.DrawString(str, font, brush, x + 10, 10);

                x = x + image.Width + 2;
                image.Dispose();
            }

            return finaImage;
        }

        /// <summary>
        /// 合并图片并添加水印
        /// </summary>
        /// <param name="framingIndex"></param>
        /// <param name="barCode"></param>
        /// <param name="machineName"></param>
        /// <param name="images"></param>
        /// <returns></returns>
        private Bitmap UnionImagesPrint(string barCode, string machineName, List<string> images)
        {
            var imageModels = new List<System.Drawing.Image>();
            foreach (var path in images)
            {
                var image = System.Drawing.Image.FromFile(path);
                imageModels.Add(image);
            }
            var finaImage = new Bitmap(imageModels.Sum(_ => _.Width), imageModels.Max(_ => _.Height));
            var sb = new StringBuilder();
            if (FramingIndex.IsPrintCode) sb.AppendLine("NO：" + barCode);
            if (FramingIndex.IsPrintLine) sb.AppendLine("Line：" + machineName);
            if (FramingIndex.IsPrintDate) sb.AppendLine("Date：" + DateTime.Now.ToString("yyyy-MM-dd"));
            if (FramingIndex.IsPrintTime) sb.AppendLine("Time：" + DateTime.Now.ToString("T"));
            try
            {
                var g = Graphics.FromImage(finaImage);
                g.Clear(Color.White);
                //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                var x = 0;
                var y = 0;
                //var position = new List<string> { "L", "Z", "R" };
                for (int i = 0; i < imageModels.Count; i++)
                {
                    var image = imageModels[i];
                    if(sb.Length > 0)
                    {
                        var gp = Graphics.FromImage(image);
                        var font = new Font("宋体 ", 80);
                        var brush = new SolidBrush(Color.Green);
                        //用于确定水印的大小
                        gp.DrawString(sb.ToString(), font, brush, new PointF(image.Width / 30, 50));
                        gp.Dispose();
                    }
                    g.DrawImage(image, x, y, image.Width, image.Height);
                    x = x + image.Width;
                    image.Dispose();
                }
                g.Dispose();
            }
            catch (Exception)
            {
                finaImage = null;
            }
            return finaImage;
        }
    }
}
